package com.dynamic.mybatis.core.parser.xml.validator;

import com.dynamic.mybatis.core.utils.StringUtils;
import org.apache.ibatis.builder.xml.XMLMapperEntityResolver;
import org.apache.ibatis.io.Resources;
import org.springframework.core.io.ClassPathResource;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * @Description
 * @Author xs
 * @Date 2023/4/6 11:14
 */
public class DmsXMLMapperEntityResolver extends XMLMapperEntityResolver {

    /**
     * 在mybatis-mapper.dtd 和 mybatis-mapper.xsd 的select 标签中添加 returnType 属性
     **/
    public enum DmsSchema {

        dms_dtd("dms-mybatis-3-mapper.dtd", "com/dynamic/mybatis/core/parser/xml/validator/dms-mybatis-3-mapper.dtd"),
        dms_xsd("dms-mybatis-mapper.xsd", "com/dynamic/mybatis/core/parser/xml/validator/dms-mybatis-mapper.xsd"),
        ;

        static Map<String, String> systemMap = new HashMap<>();

        static {
            for (DmsSchema dmsSchema : DmsSchema.values()) {
                systemMap.put(dmsSchema.systemId, dmsSchema.path);
            }
        }

        DmsSchema(String systemId, String path) {
            this.systemId = systemId;
            this.path = path;
        }

        String systemId;
        String path;

        public static void add(String systemId, String path) {
            systemMap.put(systemId, path);
        }


        public static String getSystemPath(String systemId) {
            for (Map.Entry<String, String> entry : systemMap.entrySet()) {
                String lowerCaseSystemId = systemId.toLowerCase(Locale.ENGLISH);
                if (lowerCaseSystemId.contains(entry.getKey())) {
                    return entry.getValue();
                }
            }
            return null;
        }

    }


    @Override
    public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
        try {
            if (systemId != null) {
                String path = DmsSchema.getSystemPath(systemId);
                if (StringUtils.isNotEmpty(path)) {
                    return getInputSource(path, publicId, systemId);
                } else {
                    return super.resolveEntity(publicId, systemId);
                }
            }
            return null;
        } catch (Exception e) {
            throw new SAXException(e.toString());
        }
    }

    protected InputSource getInputSource(String path, String publicId, String systemId) {
        InputSource source = null;
        if (path != null) {
            try {
                InputStream in = Resources.getResourceAsStream(path);
                source = new InputSource(in);
                source.setPublicId(publicId);
                source.setSystemId(systemId);
            } catch (IOException e) {
                // ignore, null is ok
            }
        }
        return source;
    }


    public static InputSource getMyInputSource(String packagePath, String publicId, String systemId) {
        InputSource source = null;
        try {
            InputStream in = new ClassPathResource(packagePath).getInputStream();
            source = new InputSource(in);
            source.setPublicId(publicId);
            source.setSystemId(systemId);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return source;
    }
}